package com.yichuang.wuziqi.tool;

import android.graphics.Point;
import android.util.Log;

import com.yichuang.wuziqi.game.LocalGame;

import java.util.ArrayList;

/**
 * Created by xcm on 17-12-3.
 */

public class AIAlgorithm1 {

    public static int EvaluatePosition(Point p, ArrayList<Point> myPositions, ArrayList<Point> oppositePositions) {
        return (int) (getSideScore(p, myPositions, oppositePositions) + 0.8 * getSideScore(p, oppositePositions, myPositions));
    }

    private static int getSideScore(Point p, ArrayList<Point> myPositions, ArrayList<Point> oppositePositions) {
        int score = 0;
        score += evalVertical(p, myPositions, oppositePositions);
        score += evalHorizontal(p, myPositions, oppositePositions);
        score += evalLeftDownRightUp(p, myPositions, oppositePositions);
        score += evalLeftUpRightDown(p, myPositions, oppositePositions);
        return score;
    }

    private static int evalVertical(Point p, ArrayList<Point> myPositions, ArrayList<Point> oppositePositions) {
        int x = p.x;
        int y = p.y;

        StringBuilder pattern1 = new StringBuilder();
        int count = 4;
        while (y > 0 && count > 0) {
            y--;
            count--;
            if (getPattern(myPositions, oppositePositions, x, y, pattern1)) break;
        }

        x = p.x;
        y = p.y;
        count = 4;
        StringBuilder pattern2 = new StringBuilder();
        while (y < LocalGame.MAX_LINE - 1 && count > 0) {
            y++;
            count--;
            if (getPattern(myPositions, oppositePositions, x, y, pattern2)) break;
        }

        return getPatternScore(pattern1.toString(), pattern2.reverse().toString());
    }

    private static int evalHorizontal(Point p, ArrayList<Point> myPositions, ArrayList<Point> oppositePositions) {
        int x = p.x;
        int y = p.y;

        StringBuilder pattern1 = new StringBuilder();
        int count = 4;
        while (x > 0 && count > 0) {
            x--;
            count--;
            if (getPattern(myPositions, oppositePositions, x, y, pattern1)) break;
        }

        x = p.x;
        y = p.y;
        count = 4;
        StringBuilder pattern2 = new StringBuilder();
        while (x < LocalGame.MAX_LINE - 1 && count > 0) {
            x++;
            count--;
            if (getPattern(myPositions, oppositePositions, x, y, pattern2)) break;
        }

        return getPatternScore(pattern1.toString(), pattern2.reverse().toString());
    }

    private static int evalLeftDownRightUp(Point p, ArrayList<Point> myPositions, ArrayList<Point> oppositePositions) {
        int x = p.x;
        int y = p.y;

        StringBuilder pattern1 = new StringBuilder();
        int count = 4;
        while (x > 0 && y < LocalGame.MAX_LINE - 1 && count > 0) {
            x--;
            y++;
            count--;
            if (getPattern(myPositions, oppositePositions, x, y, pattern1)) break;
        }

        x = p.x;
        y = p.y;
        count = 4;
        StringBuilder pattern2 = new StringBuilder();
        while (x < LocalGame.MAX_LINE - 1 && y > 0 && count > 0) {
            x++;
            y--;
            count--;
            if (getPattern(myPositions, oppositePositions, x, y, pattern2)) break;
        }

        return getPatternScore(pattern1.toString(), pattern2.reverse().toString());
    }

    private static int evalLeftUpRightDown(Point p, ArrayList<Point> myPositions, ArrayList<Point> oppositePositions) {
        int x = p.x;
        int y = p.y;

        StringBuilder pattern1 = new StringBuilder();
        int count = 4;
        while (x > 0 && y > 0 && count > 0) {
            x--;
            y--;
            count--;
            if (getPattern(myPositions, oppositePositions, x, y, pattern1)) break;
        }

        x = p.x;
        y = p.y;
        count = 4;
        StringBuilder pattern2 = new StringBuilder();
        while (x < LocalGame.MAX_LINE - 1 && y < LocalGame.MAX_LINE - 1 && count > 0) {
            x++;
            y++;
            count--;
            if (getPattern(myPositions, oppositePositions, x, y, pattern2)) break;
        }

        return getPatternScore(pattern1.toString(), pattern2.reverse().toString());
    }

    private static boolean getPattern(ArrayList<Point> myPositions,
                                      ArrayList<Point> oppositePositions, int x, int y,
                                      StringBuilder pattern) {
        Point newPoint = new Point(x, y);
        if (myPositions.contains(newPoint)) {
            pattern.append("1");
        } else if (oppositePositions.contains(newPoint)) {
            return true;
        } else {
            pattern.append("0");
        }
        return false;
    }

    private static int getPatternScore(String pattern1, String pattern2) {
        if (pattern1.length() + pattern2.length() < 4) {
            return 0;
        }
        return getPatternScore(pattern2 + "1" + pattern1);
    }

    //越接近11111的分数越高
    private static int getPatternScore(String pattern) {

        int i = 0, j = pattern.length() - 1;
        while (i < pattern.length() && pattern.charAt(i) == '0') {
            i++;
        }

        while (j >= 0 && pattern.charAt(j) == '0') {
            j--;
        }

        pattern = pattern.substring(i, j + 1);
        int[] array = analysePattern(pattern);
        int score = 0;
        int zeroCount = 0;
        //奇数位是1的个数,偶数为0的个数
        for (i = 0; i < array.length; i++) {
            if (array[i] != 0) {
                if (i % 2 == 0) {
                    if (zeroCount != 0) {
                        int self = myPow(8, array[i] - 1);//该位置的分数
                        score = (score + self) * (4 - zeroCount);
                    } else {
                        score += myPow(8, array[i] - 1);
                        zeroCount = 0;
                    }
                } else {
                    zeroCount = array[i];
                }
            }
        }
//        Log.d("xcm", "pattern: " + pattern + ",score=" + score);
        return score;
    }

    private static int[] analysePattern(String pattern) {
        int[] countOneAndZero = new int[9];

        int count1 = 0;
        int count0 = 0;
        boolean isOne = true;
        int index = 0;
        for (int i = 0; i < pattern.length(); i++) {
            if (pattern.charAt(i) == '1') {
                if (!isOne) {
                    //0
                    countOneAndZero[index] = count0;
                    count0 = 0;
                    index++;
                }
                isOne = true;
                count1++;
            } else if (pattern.charAt(i) == '0') {
                if (isOne) {
                    countOneAndZero[index] = count1;
                    count1 = 0;
                    index++;
                }
                isOne = false;
                count0++;
            }
        }

        countOneAndZero[index] = count1;
        return countOneAndZero;
    }

    private static int myPow(int base, int pow) {
        int result = 1;
        while (pow > 0) {
            result = result * base;
            pow--;
        }
        return result;
    }
}
